// Tierless
// Copyright © 2010 Alphora
// This file is licensed under a modified BSD-license (see tierless_license.txt).
using System;
using System.Data.Common;

namespace Tierless.Infrastructure.Data
{
	/// <summary>
	/// Provides a disposable wrapper for transactions.
	/// </summary>
	public sealed class TransactionContext : IDisposable
	{
		internal TransactionContext(ConnectionWrapper wrapper, DbTransaction transaction)
		{
			if (wrapper == null)
				throw new ArgumentException("A valid connection wrapper instance is required.");
				
			if (transaction == null)
				throw new ArgumentException("A valid transaction instance is required.");

			_wrapper = wrapper;
			Transaction = transaction;
		}
		
		private ConnectionWrapper _wrapper;

		/// <summary>
		/// Gets the underlying transaction.
		/// </summary>
		public DbTransaction Transaction { get; private set; }

		/// <summary>
		/// Gets the underlying connection.
		/// </summary>
		public DbConnection Connection
		{
			get { return _wrapper.Connection; }
		}
		
		private bool _transactionCommitted;

		/// <summary>
		/// Commits the underlying transaction and marks the context committed.
		/// </summary>
		public void Commit()
		{
			Transaction.Commit();
			_transactionCommitted = true;
		}

		/// <summary>
		/// Disposes the transaction context, and the underlying transaction.
		/// </summary>
		/// <remarks>
		/// If the transaction context is not committed, the underlying transaction is rolled back.
		/// </remarks>
		public void Dispose()
		{
			if (Transaction != null)
			{
				if (!_transactionCommitted)
				{
					try
					{
						Transaction.Rollback();
					}
					catch
					{
						// TODO: Log the error
					}
				}
				
				Transaction.Dispose();
				Transaction = null;
			}
			
			if (_wrapper != null)
			{
				_wrapper.Dispose();
				_wrapper = null;
			}
		}
	}
}
